#include "header/pyramid_body.h"
#include "header/pyramid_terasse.h"

OSG_USING_NAMESPACE

double pyra_height = 2500;
double pyra_width = 2500;
double pyra_door_height = 90;
double pyra_door_width = 70;
double pyra_door_height_begin = 100;
double pyra_roof_begin = 250;


NodePtr createPyramid()
{
	Matrix m;
	float winkel = tan(M_PI/2-atan(pyra_height/(pyra_width/2)));
	
	ImagePtr image = Image::create();
	image->read("materials/sand.jpg");
	
	//Kammer Boden Texturen laden
	ImagePtr cryptBottomImage = Image::create();
	cryptBottomImage->read("materials/cryptBottom.jpg");
	
	
	
	
	// *********** Back ***********
	// Boden
	float back_v0[3] = {0, 0, 0};
	// links unten
	float back_v1[3] = {pyra_width, 0, 0};
	
	// Oben
	float back_v2[3] = {pyra_width/2, pyra_height, pyra_width/2};
	
	// Definieren der benoetigten Typen
	GeoPTypesPtr backType = GeoPTypesUI8::create();
	beginEditCP (backType, GeoPTypesUI8::GeoPropDataFieldMask);
	{
		backType->addValue(GL_TRIANGLES);
	}
	endEditCP (backType, GeoPTypesUI8::GeoPropDataFieldMask);
	
	// Anzahl der Punkte die fuer die einzelnen Typen benoetigt werden
	GeoPLengthsPtr backLens = GeoPLengthsUI32::create();    
	beginEditCP (backLens, GeoPLengthsUI32::GeoPropDataFieldMask);
	{
		backLens->addValue(3);
	}
	endEditCP (backLens, GeoPLengthsUI32::GeoPropDataFieldMask);

	// Setzen der Punkte
	GeoPositions3fPtr backPnts = GeoPositions3f::create();
	beginEditCP (backPnts, GeoPositions3f::GeoPropDataFieldMask);
	{
		backPnts->addValue(Pnt3f(back_v0[0], back_v0[1], back_v0[2]));
		backPnts->addValue(Pnt3f(back_v1[0], back_v1[1], back_v1[2]));
		backPnts->addValue(Pnt3f(back_v2[0], back_v2[1], back_v2[2]));
	}
	endEditCP (backPnts, GeoPositions3f::GeoPropDataFieldMask);

	// Zusammenfuegen der Punkte in die oben angegebenen Formen
	GeoIndicesUI32Ptr backIndices = GeoIndicesUI32::create();
	beginEditCP (backIndices, GeoIndicesUI32::GeoPropDataFieldMask);
	{
		// hinten
		backIndices->addValue(0);
		backIndices->addValue(1);
		backIndices->addValue(2);
	}
	endEditCP (backIndices, GeoIndicesUI32::GeoPropDataFieldMask);

	GeoTexCoords2fPtr backTex = GeoTexCoords2f::create();
	beginEditCP (backTex);
	{
		backTex->addValue(Vec2f(back_v0[0]/pyra_width, back_v0[1]/pyra_height));
		backTex->addValue(Vec2f(back_v1[0]/pyra_width, back_v1[1]/pyra_height));

		backTex->addValue(Vec2f(back_v2[0]/pyra_width, back_v2[1]/pyra_height));
	}
	endEditCP (backTex);
	
	GeoNormals3fPtr backNorms = GeoNormals3f::create();
	beginEditCP(backNorms, GeoNormals3f::GeoPropDataFieldMask);
	{
		float vector1[3];
		float vector2[3];
		float erg[3];
		float norm[3];

		for(int i = 0; i < 3; i++) {
			 vector1[i] = back_v1[i] - back_v0[i];
			 vector2[i] = back_v2[i] - back_v0[i];
		}
		erg[0] = vector1[1]*vector2[2]-vector1[2]*vector2[1];
		erg[1] = vector1[2]*vector2[0]-vector1[0]*vector2[2];
		erg[2] = vector1[0]*vector2[1]-vector1[1]*vector2[0];
		norm[0] = (1/sqrt(pow(erg[0],2)+pow(erg[1],2)+pow(erg[2],2)))*erg[0];
		norm[1] = (1/sqrt(pow(erg[0],2)+pow(erg[1],2)+pow(erg[2],2)))*erg[1];
		norm[2] = (1/sqrt(pow(erg[0],2)+pow(erg[1],2)+pow(erg[2],2)))*erg[2];
		
		for (int i = 0; i < 3; i++)
			 backNorms->addValue(Vec3f(norm[0], norm[1], norm[2]));
		
		//backNorms->addValue(Vec3f(0, 1, -2));
	}
	endEditCP (backNorms, GeoNormals3f::GeoPropDataFieldMask);

			 
	SimpleTexturedMaterialPtr m1 = SimpleTexturedMaterial::create();	     
	// when everything is changed, not setting the mask is ok
	beginEditCP(m1);
	{
		m1->setAmbient      (Color3f(0.3,0.3,0.3));
		m1->setDiffuse      (Color3f(0.8,0.8,0.8));
		m1->setEmission     (Color3f(0.0,0.0,0.0));
		m1->setSpecular     (Color3f(1.0,1.0,1.0));
		m1->setShininess    (20);
		m1->setTransparency (0);
		m1->setColorMaterial(GL_NONE);
		
		m1->setImage	 (image);
		m1->setMinFilter    (GL_LINEAR_MIPMAP_LINEAR);
		m1->setMagFilter    (GL_LINEAR);
		m1->setEnvMode      (GL_MODULATE);
	}
	endEditCP (m1);
	
	
	// Zusammenfuegen der Eigenschaften
	GeometryPtr backgeo=Geometry::create();
	beginEditCP (backgeo, Geometry::TypesFieldMask    |
			 Geometry::LengthsFieldMask   |
			 Geometry::IndicesFieldMask   |
			 Geometry::PositionsFieldMask |
			 Geometry::NormalsFieldMask   |
			 Geometry::MaterialFieldMask  );
	{
		backgeo->setTypes    (backType);
		backgeo->setLengths  (backLens);
		backgeo->setIndices  (backIndices);
		backgeo->setTexCoords(backTex);
		backgeo->setPositions(backPnts);
		backgeo->setNormals  (backNorms);
		backgeo->setMaterial (m1);
	}
	endEditCP (backgeo, Geometry::TypesFieldMask    |
			 Geometry::LengthsFieldMask   |
			 Geometry::IndicesFieldMask   |
			 Geometry::PositionsFieldMask |
			 Geometry::NormalsFieldMask   |
			 Geometry::MaterialFieldMask  );

	// Erstellen eines Knotens
	NodePtr back = Node::create();
	beginEditCP(back, Node::CoreFieldMask);
	{
		back->setCore(backgeo);
	}
	endEditCP  (back, Node::CoreFieldMask);
	
	setName(back, "pyraBodyBack");
	
	
	
	
	
	// *********** Left ***********
	// Boden
	float left_v0[3] = {0, 0, 0};
	// links unten
	float left_v1[3] = {0, 0, pyra_width};
	
	// Oben
	float left_v2[3] = {pyra_width/2, pyra_height, pyra_width/2};
	
	// Definieren der benoetigten Typen
	GeoPTypesPtr leftType = GeoPTypesUI8::create();
	beginEditCP (leftType, GeoPTypesUI8::GeoPropDataFieldMask);
	{
		leftType->addValue(GL_TRIANGLES);
	}
	endEditCP (leftType, GeoPTypesUI8::GeoPropDataFieldMask);
	
	// Anzahl der Punkte die fuer die einzelnen Typen benoetigt werden
	GeoPLengthsPtr leftLens = GeoPLengthsUI32::create();    
	beginEditCP (leftLens, GeoPLengthsUI32::GeoPropDataFieldMask);
	{
		leftLens->addValue(3);
	}
	endEditCP (leftLens, GeoPLengthsUI32::GeoPropDataFieldMask);

	// Setzen der Punkte
	GeoPositions3fPtr leftPnts = GeoPositions3f::create();
	beginEditCP (leftPnts, GeoPositions3f::GeoPropDataFieldMask);
	{
		leftPnts->addValue(Pnt3f(left_v0[0], left_v0[1], left_v0[2]));
		leftPnts->addValue(Pnt3f(left_v1[0], left_v1[1], left_v1[2]));
		leftPnts->addValue(Pnt3f(left_v2[0], left_v2[1], left_v2[2]));
	}
	endEditCP (leftPnts, GeoPositions3f::GeoPropDataFieldMask);

	// Zusammenfuegen der Punkte in die oben angegebenen Formen
	GeoIndicesUI32Ptr leftIndices = GeoIndicesUI32::create();
	beginEditCP (leftIndices, GeoIndicesUI32::GeoPropDataFieldMask);
	{
		// links
		leftIndices->addValue(0);
		leftIndices->addValue(1);
		leftIndices->addValue(2);
	}
	endEditCP (leftIndices, GeoIndicesUI32::GeoPropDataFieldMask);


	GeoTexCoords2fPtr leftTex = GeoTexCoords2f::create();
	beginEditCP (leftTex);
	{
		leftTex->addValue(Vec2f(left_v0[1]/pyra_height, left_v0[2]/pyra_width));
		leftTex->addValue(Vec2f(left_v1[1]/pyra_height, left_v1[2]/pyra_width));
		leftTex->addValue(Vec2f(left_v2[1]/pyra_height, left_v2[2]/pyra_width));
	}
	endEditCP (leftTex);
	
	GeoNormals3fPtr leftNorms = GeoNormals3f::create();
	beginEditCP(leftNorms, GeoNormals3f::GeoPropDataFieldMask);
	{
		float vector1[3];
		float vector2[3];
		float erg[3];
		float norm[3];

		for(int i = 0; i < 3; i++) {
			 vector1[i] = left_v1[i] - left_v0[i];
			 vector2[i] = left_v2[i] - left_v0[i];
		}
		erg[0] = vector1[1]*vector2[2]-vector1[2]*vector2[1];
		erg[1] = vector1[2]*vector2[0]-vector1[0]*vector2[2];
		erg[2] = vector1[0]*vector2[1]-vector1[1]*vector2[0];
		norm[0] = (1/sqrt(pow(erg[0],2)+pow(erg[1],2)+pow(erg[2],2)))*erg[0];
		norm[1] = (1/sqrt(pow(erg[0],2)+pow(erg[1],2)+pow(erg[2],2)))*erg[1];
		norm[2] = (1/sqrt(pow(erg[0],2)+pow(erg[1],2)+pow(erg[2],2)))*erg[2];
		
		for (int i = 0; i < 3; i++)
			 leftNorms->addValue(-Vec3f(norm[0], norm[1], norm[2]));
		
		//leftNorms->addValue(Vec3f(2, -1, 0));
	}
	endEditCP (leftNorms, GeoNormals3f::GeoPropDataFieldMask);
	
	// Zusammenfuegen der Eigenschaften
	GeometryPtr leftgeo=Geometry::create();
	beginEditCP (leftgeo, Geometry::TypesFieldMask    |
			 Geometry::LengthsFieldMask   |
			 Geometry::IndicesFieldMask   |
			 Geometry::PositionsFieldMask |
			 Geometry::NormalsFieldMask   |
			 Geometry::MaterialFieldMask  );
	{
		leftgeo->setTypes    (leftType);
		leftgeo->setLengths  (leftLens);
		leftgeo->setIndices  (leftIndices);
		leftgeo->setTexCoords(leftTex);
		leftgeo->setPositions(leftPnts);
		leftgeo->setNormals  (leftNorms);
		leftgeo->setMaterial (m1);
	}
	endEditCP (leftgeo, Geometry::TypesFieldMask    |
			 Geometry::LengthsFieldMask   |
			 Geometry::IndicesFieldMask   |
			 Geometry::PositionsFieldMask |
			 Geometry::NormalsFieldMask   |
			 Geometry::MaterialFieldMask  );

	// Erstellen eines Knotens
	NodePtr left = Node::create();
	beginEditCP(left, Node::CoreFieldMask);
	{
		left->setCore(leftgeo);
	}
	endEditCP  (left, Node::CoreFieldMask);
	
	setName(left, "pyraBodyLeft");
	
	
	
	
	// *********** Right ***********	 
	// Boden
	float right_v0[3] = {pyra_width, 0, 0};
	// links unten
	float right_v1[3] = {pyra_width, 0, pyra_width};
	
	// Oben
	float right_v2[3] = {pyra_width/2, pyra_height, pyra_width/2};
	
	// Definieren der benoetigten Typen
	GeoPTypesPtr rightType = GeoPTypesUI8::create();
	beginEditCP (rightType, GeoPTypesUI8::GeoPropDataFieldMask);
	{
		rightType->addValue(GL_TRIANGLES);
	}
	endEditCP (rightType, GeoPTypesUI8::GeoPropDataFieldMask);
	
	// Anzahl der Punkte die fuer die einzelnen Typen benoetigt werden
	GeoPLengthsPtr rightLens = GeoPLengthsUI32::create();    
	beginEditCP (rightLens, GeoPLengthsUI32::GeoPropDataFieldMask);
	{
		rightLens->addValue(3);
	}
	endEditCP (rightLens, GeoPLengthsUI32::GeoPropDataFieldMask);

	// Setzen der Punkte
	GeoPositions3fPtr rightPnts = GeoPositions3f::create();
	beginEditCP (rightPnts, GeoPositions3f::GeoPropDataFieldMask);
	{
		rightPnts->addValue(Pnt3f(right_v0[0], right_v0[1], right_v0[2]));
		rightPnts->addValue(Pnt3f(right_v1[0], right_v1[1], right_v1[2]));
		rightPnts->addValue(Pnt3f(right_v2[0], right_v2[1], right_v2[2]));
	}
	endEditCP (rightPnts, GeoPositions3f::GeoPropDataFieldMask);

	// Zusammenfuegen der Punkte in die oben angegebenen Formen
	GeoIndicesUI32Ptr rightIndices = GeoIndicesUI32::create();
	beginEditCP (rightIndices, GeoIndicesUI32::GeoPropDataFieldMask);
	{
		// rechts
		rightIndices->addValue(0);
		rightIndices->addValue(1);
		rightIndices->addValue(2);
	}
	endEditCP (rightIndices, GeoIndicesUI32::GeoPropDataFieldMask);

	GeoTexCoords2fPtr rightTex = GeoTexCoords2f::create();
	beginEditCP (rightTex);
	{
		rightTex->addValue(Vec2f(right_v0[1]/pyra_height, right_v0[2]/pyra_width));
		rightTex->addValue(Vec2f(right_v1[1]/pyra_height, right_v1[2]/pyra_width));
		rightTex->addValue(Vec2f(right_v2[1]/pyra_height, right_v2[2]/pyra_width));
	}
	endEditCP (rightTex);  
	
	GeoNormals3fPtr rightNorms = GeoNormals3f::create();
	beginEditCP(rightNorms, GeoNormals3f::GeoPropDataFieldMask);
	{
		float vector1[3];
		float vector2[3];
		float erg[3];
		float norm[3];

		for(int i = 0; i < 3; i++) {
			 vector1[i] = right_v1[i] - right_v0[i];
			 vector2[i] = right_v2[i] - right_v0[i];
		}
		erg[0] = vector1[1]*vector2[2]-vector1[2]*vector2[1];
		erg[1] = vector1[2]*vector2[0]-vector1[0]*vector2[2];
		erg[2] = vector1[0]*vector2[1]-vector1[1]*vector2[0];
		norm[0] = (1/sqrt(pow(erg[0],2)+pow(erg[1],2)+pow(erg[2],2)))*erg[0];
		norm[1] = (1/sqrt(pow(erg[0],2)+pow(erg[1],2)+pow(erg[2],2)))*erg[1];
		norm[2] = (1/sqrt(pow(erg[0],2)+pow(erg[1],2)+pow(erg[2],2)))*erg[2];
		
		for (int i = 0; i < 3; i++)
			 rightNorms->addValue(Vec3f(norm[0], norm[1], norm[2]));
		
		//rightNorms->addValue(Vec3f(2, 1, 0));
	}
	endEditCP (rightNorms, GeoNormals3f::GeoPropDataFieldMask);
	
	// Zusammenfuegen der Eigenschaften
	GeometryPtr rightgeo=Geometry::create();
	beginEditCP (rightgeo, Geometry::TypesFieldMask    |
			 Geometry::LengthsFieldMask   |
			 Geometry::IndicesFieldMask   |
			 Geometry::PositionsFieldMask |
			 Geometry::NormalsFieldMask   |
			 Geometry::MaterialFieldMask  );
	{
		rightgeo->setTypes    (rightType);
		rightgeo->setLengths  (rightLens);
		rightgeo->setIndices  (rightIndices);
		rightgeo->setTexCoords(rightTex);
		rightgeo->setPositions(rightPnts);
		rightgeo->setNormals  (rightNorms);
		rightgeo->setMaterial (m1);
	}
	endEditCP (rightgeo, Geometry::TypesFieldMask    |
			 Geometry::LengthsFieldMask   |
			 Geometry::IndicesFieldMask   |
			 Geometry::PositionsFieldMask |
			 Geometry::NormalsFieldMask   |
			 Geometry::MaterialFieldMask  );

	// Erstellen eines Knotens
	NodePtr right = Node::create();
	beginEditCP(right, Node::CoreFieldMask);
	{
		right->setCore(rightgeo);
	}
	endEditCP  (right, Node::CoreFieldMask);
	
	setName(right, "pyraBodyRight");
	
	
	
	
	
	
	// *********** Front ***********
	// Boden
	float front_v0[3] = {0, 0, pyra_width};
	float front_v1[3] = {pyra_width, 0, pyra_width};

	// Oben
	float front_v2[3] = {pyra_width/2, pyra_height, pyra_width/2};

	// Tuer
	// links unten
	float front_v3[3] = {pyra_width/2-pyra_door_width/2,
			 pyra_door_height_begin,
			 pyra_width-winkel*pyra_door_height_begin};
	// links oben
	float front_v4[3] = {pyra_width/2-pyra_door_width/2,
			 pyra_door_height_begin+pyra_door_height,
			 pyra_width-winkel*(pyra_door_height+pyra_door_height_begin)};
	// rechts oben
	float front_v5[3] = {pyra_width/2+pyra_door_width/2,
			 pyra_door_height_begin+pyra_door_height,
			 pyra_width-winkel*(pyra_door_height+pyra_door_height_begin)};
	// rechts unten
	float front_v6[3] = {pyra_width/2+pyra_door_width/2,
			 pyra_door_height_begin,
			 pyra_width-winkel*pyra_door_height_begin};
	
	// links mitte
	float front_v7[3] = {winkel*(pyra_door_height+pyra_door_height_begin),
			 pyra_door_height_begin+pyra_door_height,
			 pyra_width-winkel*(pyra_door_height+pyra_door_height_begin)};
	// rechts mitte
	float front_v8[3] = {pyra_width-winkel*(pyra_door_height+pyra_door_height_begin),
			 pyra_door_height_begin+pyra_door_height,
			 pyra_width-winkel*(pyra_door_height+pyra_door_height_begin)};
	
	// Definieren der benoetigten Typen
	GeoPTypesPtr frontType = GeoPTypesUI8::create();
	beginEditCP (frontType, GeoPTypesUI8::GeoPropDataFieldMask);
	{
		frontType->addValue(GL_QUADS);
		//frontType->addValue(GL_POLYGON);
		frontType->addValue(GL_TRIANGLES);
	}
	endEditCP (frontType, GeoPTypesUI8::GeoPropDataFieldMask);
	
	// Anzahl der Punkte die fuer die einzelnen Typen benoetigt werden
	GeoPLengthsPtr frontLens = GeoPLengthsUI32::create();    
	beginEditCP (frontLens, GeoPLengthsUI32::GeoPropDataFieldMask);
	{
		frontLens->addValue(4);
		//frontLens->addValue(5);
		frontLens->addValue(21);
	}
	endEditCP (frontLens, GeoPLengthsUI32::GeoPropDataFieldMask);


	// Setzen der Punkte
	GeoPositions3fPtr frontPnts = GeoPositions3f::create();
	beginEditCP (frontPnts, GeoPositions3f::GeoPropDataFieldMask);
	{
		frontPnts->addValue(Pnt3f(front_v0[0], front_v0[1], front_v0[2]));
		frontPnts->addValue(Pnt3f(front_v1[0], front_v1[1], front_v1[2]));
		frontPnts->addValue(Pnt3f(front_v2[0], front_v2[1], front_v2[2]));
		frontPnts->addValue(Pnt3f(front_v3[0], front_v3[1], front_v3[2]));
		frontPnts->addValue(Pnt3f(front_v4[0], front_v4[1], front_v4[2]));
		frontPnts->addValue(Pnt3f(front_v5[0], front_v5[1], front_v5[2]));
		frontPnts->addValue(Pnt3f(front_v6[0], front_v6[1], front_v6[2]));
		frontPnts->addValue(Pnt3f(front_v7[0], front_v7[1], front_v7[2]));
		frontPnts->addValue(Pnt3f(front_v8[0], front_v8[1], front_v8[2]));
	}
	endEditCP (frontPnts, GeoPositions3f::GeoPropDataFieldMask);

	// Zusammenfuegen der Punkte in die oben angegebenen Formen
	GeoIndicesUI32Ptr frontIndices = GeoIndicesUI32::create();
	beginEditCP (frontIndices, GeoIndicesUI32::GeoPropDataFieldMask);
	{
		// vorne		 
		// unten
		frontIndices->addValue(0);
		frontIndices->addValue(3);
		frontIndices->addValue(6);
		frontIndices->addValue(1);

		frontIndices->addValue(0);
		frontIndices->addValue(3);
		frontIndices->addValue(4);

		frontIndices->addValue(0);
		frontIndices->addValue(4);
		frontIndices->addValue(7);
		
		frontIndices->addValue(1);
		frontIndices->addValue(6);
		frontIndices->addValue(5);

		frontIndices->addValue(1);
		frontIndices->addValue(5);
		frontIndices->addValue(8);

		frontIndices->addValue(2);
		frontIndices->addValue(4);
		frontIndices->addValue(7);

		frontIndices->addValue(2);
		frontIndices->addValue(5);
		frontIndices->addValue(8);

		frontIndices->addValue(2);
		frontIndices->addValue(4);
		frontIndices->addValue(5);
	}
	endEditCP (frontIndices, GeoIndicesUI32::GeoPropDataFieldMask);

	GeoTexCoords2fPtr frontTex = GeoTexCoords2f::create();
	beginEditCP (frontTex);
	{
		frontTex->addValue(Vec2f(front_v0[0]/pyra_width, front_v0[1]/pyra_height));
		frontTex->addValue(Vec2f(front_v1[0]/pyra_width, front_v1[1]/pyra_height));

		frontTex->addValue(Vec2f(front_v2[0]/pyra_width, front_v2[1]/pyra_height));

		frontTex->addValue(Vec2f(front_v3[0]/pyra_width, front_v3[1]/pyra_height));
		frontTex->addValue(Vec2f(front_v4[0]/pyra_width, front_v4[1]/pyra_height));
		frontTex->addValue(Vec2f(front_v5[0]/pyra_width, front_v5[1]/pyra_height));
		frontTex->addValue(Vec2f(front_v6[0]/pyra_width, front_v6[1]/pyra_height));

		frontTex->addValue(Vec2f(front_v7[0]/pyra_width, front_v7[1]/pyra_height));
		frontTex->addValue(Vec2f(front_v8[0]/pyra_width, front_v8[1]/pyra_height));
	}
	endEditCP (frontTex);
	
	GeoNormals3fPtr frontNorms = GeoNormals3f::create();
	beginEditCP(frontNorms, GeoNormals3f::GeoPropDataFieldMask);
	{
		float vector1[3];
		float vector2[3];
		float erg[3];
		float norm[3];

		for(int i = 0; i < 3; i++) {
			 vector1[i] = front_v1[i] - front_v0[i];
			 vector2[i] = front_v2[i] - front_v0[i];
		}
		erg[0] = vector1[1]*vector2[2]-vector1[2]*vector2[1];
		erg[1] = vector1[2]*vector2[0]-vector1[0]*vector2[2];
		erg[2] = vector1[0]*vector2[1]-vector1[1]*vector2[0];
		norm[0] = (1/sqrt(pow(erg[0],2)+pow(erg[1],2)+pow(erg[2],2)))*erg[0];
		norm[1] = (1/sqrt(pow(erg[0],2)+pow(erg[1],2)+pow(erg[2],2)))*erg[1];
		norm[2] = (1/sqrt(pow(erg[0],2)+pow(erg[1],2)+pow(erg[2],2)))*erg[2];
		
		for (int i = 0; i < 8; i++)
			 frontNorms->addValue(Vec3f(norm[0], norm[1], norm[2]));
		
		/*
		frontNorms->addValue(Vec3f(0, -1, -2));
		frontNorms->addValue(Vec3f(0, -1, -2));
		frontNorms->addValue(Vec3f(0, -1, -2));
		frontNorms->addValue(Vec3f(0, -1, -2));
		frontNorms->addValue(Vec3f(0, -1, -2));
		frontNorms->addValue(Vec3f(0, -1, -2));
		*/
	}
	endEditCP (frontNorms, GeoNormals3f::GeoPropDataFieldMask);
	
	// Zusammenfuegen der Eigenschaften
	GeometryPtr frontgeo=Geometry::create();
	beginEditCP (frontgeo, Geometry::TypesFieldMask    |
			 Geometry::LengthsFieldMask   |
			 Geometry::IndicesFieldMask   |
			 Geometry::PositionsFieldMask |
			 Geometry::NormalsFieldMask   |
			 Geometry::MaterialFieldMask  );
	{
		frontgeo->setTypes    (frontType);
		frontgeo->setLengths  (frontLens);
		frontgeo->setIndices  (frontIndices);
		frontgeo->setTexCoords(frontTex);
		frontgeo->setPositions(frontPnts);
		rightgeo->setNormals  (frontNorms);
		//calcFaceNormals(frontgeo);
		frontgeo->setMaterial (m1);
	}
	endEditCP (frontgeo, Geometry::TypesFieldMask    |
			 Geometry::LengthsFieldMask   |
			 Geometry::IndicesFieldMask   |
			 Geometry::PositionsFieldMask |
			 Geometry::NormalsFieldMask   |
			 Geometry::MaterialFieldMask  );

	// Erstellen eines Knotens
	NodePtr front = Node::create();
	beginEditCP(front, Node::CoreFieldMask);
	{
		front->setCore(frontgeo);
	}
	endEditCP  (front, Node::CoreFieldMask);
	
	setName(front, "pyraBodyFront");
	
	
	
	// *********** Dach ***********
	NodePtr roof = makeBox(pyra_width-pyra_roof_begin-5,10, pyra_width-pyra_roof_begin-5, 10, 10, 10);
	setName(roof, "pyraBodyRoof");
	
	TransformPtr troof = Transform::create();
	beginEditCP(troof, Transform::MatrixFieldMask);
		m.setIdentity();
		m.setTranslate(pyra_width/2, pyra_roof_begin-10/2-5/2, pyra_width/2);
		troof->setMatrix(m);
	endEditCP(troof, Transform::MatrixFieldMask);
	
	NodePtr roofTrans = Node::create();
	beginEditCP(roofTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);
		roofTrans->setCore(troof);
		roofTrans->addChild(roof);
	endEditCP(roofTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);
	
	
	
	
	// *********** Boden ***********
	NodePtr bottom = makeBox(pyra_width-pyra_door_height_begin-5,10, pyra_width-pyra_door_height_begin-5, 10, 10, 10);
	setName(bottom, "pyraBodyBottom");
	
	TransformPtr tbottom = Transform::create();
	beginEditCP(tbottom, Transform::MatrixFieldMask);
		m.setIdentity();
		m.setTranslate(pyra_width/2, pyra_door_height_begin-10/2-5/2, pyra_width/2);
		tbottom->setMatrix(m);
	endEditCP(tbottom, Transform::MatrixFieldMask);
	
	NodePtr bottomTrans = Node::create();
	beginEditCP(bottomTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);
		bottomTrans->setCore(tbottom);
		bottomTrans->addChild(bottom);
	endEditCP(bottomTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);
	
  
	
	
	//Aus dem Bild eine Textur machen
	TextureChunkPtr cryptBottomTex = TextureChunk::create();
	beginEditCP(cryptBottomTex);
		cryptBottomTex->setImage(cryptBottomImage);
		cryptBottomTex->setMinFilter(GL_LINEAR);
		cryptBottomTex->setMagFilter(GL_LINEAR);
		cryptBottomTex->setWrapS(GL_REPEAT);
		cryptBottomTex->setWrapT(GL_REPEAT);
		cryptBottomTex->setScale(0.2);
		cryptBottomTex->setEnvMode(GL_MODULATE);
	endEditCP(cryptBottomTex);
	  
	SimpleMaterialPtr cryptBottomMat = SimpleMaterial::create();
	beginEditCP(cryptBottomMat);
		//Materialfarbe bei seitlicher Ansicht (Brechungswinkel)
		cryptBottomMat->setAmbient(Color3f(0.3, 0.3, 0.3));    
		//Bestimmt Farbe des Materials
		cryptBottomMat->setDiffuse(Color3f(1.0, 1.0, 1.0));
		cryptBottomMat->addChunk(cryptBottomTex);
	endEditCP(cryptBottomMat);

	//Mittelpunkt des Texturtraegers heraus finden und die Textur darauf legen.
	GeometryPtr cryptBottomGeo = GeometryPtr::dcast(bottom->getCore());
	beginEditCP(cryptBottomGeo);
		cryptBottomGeo->setMaterial(cryptBottomMat);
	endEditCP(cryptBottomGeo);
	//Ende Boden Textur
	
	


	
	// *********** Terasse ***********
	NodePtr terasse = createTerasse();
	
	// Transformation
	TransformPtr tterasse = Transform::create();
	beginEditCP(tterasse, Transform::MatrixFieldMask);
		m.setIdentity();
		m.setTranslate(0, 0, 0);
		tterasse->setMatrix(m);
	endEditCP(tterasse, Transform::MatrixFieldMask);
		
	NodePtr terasseTrans = Node::create();
	beginEditCP(terasseTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);
		terasseTrans->setCore(tterasse);
		terasseTrans->addChild(terasse);
	endEditCP(terasseTrans, Node::CoreFieldMask | Node::ChildrenFieldMask);

	// *********** show all normals ***********


/*	NodePtr left_norm = calcVertexNormalsGeo(leftgeo, 50.0);
    SimpleMaterialPtr mat = SimpleMaterial::create();
    
    GeometryPtr geo = GeometryPtr::dcast(left_norm->getCore());
    beginEditCP(geo);
        geo->setMaterial(mat);
    endEditCP(geo);

	NodePtr right_norm = calcVertexNormalsGeo(rightgeo, 50.0);
    
     geo = GeometryPtr::dcast(right_norm->getCore());
    beginEditCP(geo);
        geo->setMaterial(mat);
    endEditCP(geo);

	NodePtr front_norm = calcVertexNormalsGeo(frontgeo, 50.0);
    
     geo = GeometryPtr::dcast(front_norm->getCore());
    beginEditCP(geo);
        geo->setMaterial(mat);
    endEditCP(geo);

	NodePtr back_norm = calcVertexNormalsGeo(backgeo, 50.0);
    
     geo = GeometryPtr::dcast(back_norm->getCore());
    beginEditCP(geo);
        geo->setMaterial(mat);
    endEditCP(geo);
*/	


	
	// Erstellen eines Knotens
	NodePtr holePyra = Node::create();
	beginEditCP(holePyra, Node::CoreFieldMask);
	{
		holePyra->setCore(Group::create());
		holePyra->addChild(roofTrans);
		holePyra->addChild(bottomTrans);

		holePyra->addChild(back);
		holePyra->addChild(left);
		holePyra->addChild(right);
		holePyra->addChild(front);

		//holePyra->addChild(left_norm);
		//holePyra->addChild(right_norm);
		//holePyra->addChild(back_norm);
		//holePyra->addChild(front_norm);

		holePyra->addChild(terasseTrans);
	}
	endEditCP  (holePyra, Node::CoreFieldMask);
	
	
	return holePyra;
}
